package com.qianfeng.smartdevice.service.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qianfeng.smartdevice.dto.UserDto;
import com.qianfeng.smartdevice.enums.CheckType;
import com.qianfeng.smartdevice.enums.LoginResultEnum;
import com.qianfeng.smartdevice.event.MyloginEvent;
import com.qianfeng.smartdevice.execption.AddDataErrorException;
import com.qianfeng.smartdevice.execption.MyErrorCode;
import com.qianfeng.smartdevice.execption.QueryDataErrorException;
import com.qianfeng.smartdevice.mapper.SysUserInfoMapper;
import com.qianfeng.smartdevice.pojo.SysUserInfo;
import com.qianfeng.smartdevice.service.SysUserService;
import com.qianfeng.smartdevice.utils.MD5Utils;
import com.qianfeng.smartdevice.utils.MyStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * Created by wenka on 2022/3/14 16:48
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Service
@Transactional
public class SysUserServiceImpl implements SysUserService {
    private SysUserInfoMapper sysUserInfoMapper;
    private ApplicationContext context;

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Autowired
    public void setSysUserInfoMapper(SysUserInfoMapper sysUserInfoMapper) {
        this.sysUserInfoMapper = sysUserInfoMapper;
    }

    Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Override
    public SysUserInfo findById(Long userId) {
        return sysUserInfoMapper.findById(userId);
    }

    @Override
    public PageInfo<SysUserInfo> findAll(int pageSize, int paegNum) {
        PageHelper.startPage(paegNum, pageSize);
        List<SysUserInfo> sysUserInfoList = sysUserInfoMapper.findAll();
        PageInfo<SysUserInfo> userInfoPageInfo = new PageInfo<>(sysUserInfoList);
        return userInfoPageInfo;
    }


    @Override
    public void addUser(SysUserInfo sysUserInfo) {
        //校验
        //传递数据不能为空
        Assert.isTrue(!sysUserInfo.isEmpty(CheckType.ADD), () -> {
            throw new AddDataErrorException("数据为空", MyErrorCode.DATA_NULL);
        });
        //校验手机号格式
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getPhone(), MyStringUtils.mobileRegex), () -> {
            throw new AddDataErrorException("手机号不合法", MyErrorCode.PHONE_REG_NOT_MACTH);
        });
        //校验邮箱格式
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getEmail(), MyStringUtils.emaiRegex), () -> {
            throw new AddDataErrorException("邮箱格式不正确", MyErrorCode.MAIL_REG_NOT_MACTH);
        });
        //校验唯一的数据
        //用户名 手机 邮箱 必须检查
        SysUserInfo info = sysUserInfoMapper.findByUsername(sysUserInfo.getUsername());
        //用户名以存在
        info = sysUserInfoMapper.findByUsername(sysUserInfo.getUsername());
        Assert.isNull(info, () -> {
            throw new AddDataErrorException("用户名已存在", MyErrorCode.USER_ALREADY_EXIST);
        });
        //手机号是否存在
        info = sysUserInfoMapper.findByPhone(sysUserInfo.getPhone());
        Assert.isNull(info, () -> {
            throw new AddDataErrorException("手机号已存在", MyErrorCode.PHONE_ALREADY_EXIST);
        });
        //邮箱已存在
        info = sysUserInfoMapper.findByEmail(sysUserInfo.getEmail());
        Assert.isNull(info, () -> {
            throw new AddDataErrorException("邮箱已存在", MyErrorCode.EMAIL_ALREADY_EXIST);
        });

        //生产长度为10的盐
        String salt = MD5Utils.getRandomString(10);
        //添加盐
        sysUserInfo.setPwdSalt(salt);
        //生成密码
        //计算MD5值
        String md5 = MD5Utils.getMd5(sysUserInfo.getPassword(), salt, 2048);
        //将密码替换成MD5值
        sysUserInfo.setPassword(md5);
        //创建默认属性
        sysUserInfo.setCreateTime(new Date());
        //检查当前登录的用户，如果是管理员，设置管理员信息，如果没有用户就创建
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户");
        //保存到数据库
        sysUserInfoMapper.addUser(sysUserInfo);
        logger.error("添加数据成功");

    }

    @Override
    public SysUserInfo findByUserNameAndPassword(String username, String password) {
        return null;
    }

    @Override
    public SysUserInfo login(UserDto userDto) {

        //传递的数据不能为空
        Assert.isTrue(StringUtils.hasText(userDto.getUsername()) && StringUtils.hasText(userDto.getPassword()), () -> {
            throw new QueryDataErrorException("用户名密码不能为空", MyErrorCode.DATA_NULL);
        });
        //只能根据用户名查询数据
        SysUserInfo userInfo = sysUserInfoMapper.findByUsername(userDto.getUsername());
        //判断用户名密码是否正确
        Assert.notNull(userInfo, () -> {

            throw new QueryDataErrorException("用户名密码不正确", MyErrorCode.USERNAME_PASSWORD_ERROR);
        });
        //查询到了就获取盐
        String pwdSalt = userInfo.getPwdSalt();
        //用获取到的盐计算散列值，跟注册时的方法一致
        String md5 = MD5Utils.getMd5(userDto.getPassword(), pwdSalt, 2048);
        //与登录的密码相比较
        Assert.isTrue(md5.equalsIgnoreCase(userInfo.getPassword()), () -> {
            context.publishEvent(new MyloginEvent(LoginResultEnum.FAIL,userDto.getUsername()));
            throw new QueryDataErrorException("用户名密码错误", MyErrorCode.USERNAME_PASSWORD_ERROR);
        });
        //不能把数据传到前端页面
        userInfo.setPwdSalt(null);
        userInfo.setPassword(null);
        context.publishEvent(new MyloginEvent(LoginResultEnum.SUCCESS,userDto.getUsername()));
        return userInfo;
    }


}
